package com.google.code.mochaccino.framework.util;
/*
 * Copyright 2012 Claude Houle claude.houle@gmail.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import com.thoughtworks.xstream.MarshallingStrategy;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider;
import com.thoughtworks.xstream.core.ReferenceByXPathMarshallingStrategy;
import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import org.apache.commons.io.IOUtils;

/**
 * This class is a collection of serialization method(s) utilities to facilitate Object
 * Serialization. Supporting both regular serialization and XML Serialization
 */
public final class SerializationUtil {
	private SerializationUtil() {
	}

	/**
	 * Read Object from byte array
	 *
	 * @param bytes The Byte Array that is composing the object
	 * @return Object The Object
	 */
	public static Object deserialize( byte[] bytes ) throws IOException, ClassNotFoundException {
		return deserialize( new ByteArrayInputStream( bytes ) );
	}

	/**
	 * Read Object from file
	 *
	 * @param file The File to deserialize from
	 * @return Object the Object
	 */
	public static Object deserialize( File file ) throws IOException, ClassNotFoundException {
		return deserialize( new FileInputStream( file ) );
	}

	/** Read Object from input stream */
	public static Object deserialize( InputStream input ) throws IOException, ClassNotFoundException {
		ObjectInputStream out = new ObjectInputStream( new BufferedInputStream( input ) );
		Object object = out.readObject();
		out.close();
		return object;
	}

	/** Read xml Object from bytes */
	public static Object deserializeFromXML( byte[] bytes ) {
		return deserializeFromXML( new ByteArrayInputStream( bytes ) );
	}

	/** Read xml Object from file */
	public static Object deserializeFromXML( File content ) throws IOException {
		return deserializeFromXML( new FileInputStream( content ) );
	}

	/** Read xml Object from inputstream */
	public static Object deserializeFromXML( InputStream content ) {
		XMLDecoder out = new XMLDecoder( new BufferedInputStream( content ) );
		Object object = out.readObject();
		out.close();
		return object;
	}

	/** Deserialize from XStream */
	public static Object deserializeFromXStream( byte[] in ) {
		return deserializeFromXStream( new ByteArrayInputStream( in ) );
	}

	/** Deserialize from XStream */
	public static Object deserializeFromXStream( File in ) throws IOException {
		return deserializeFromXStream( new FileInputStream( in ) );
	}

	/** Deserialize from XStream */
	public static Object deserializeFromXStream( InputStream in ) {
		XStream x = new XStream();
		return x.fromXML( in );
	}

	/** Write Object to bytes */
	public static byte[] serialize( Serializable obj ) throws IOException {
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		serialize( obj, out );
		return out.toByteArray();
	}

	/** Write Object to file */
	public static void serialize( Serializable obj, File out ) throws IOException {
		serialize( obj, new FileOutputStream( out ) );
	}

	/** Write Object to outputstream */
	public static void serialize( Serializable obj, OutputStream output ) throws IOException {
		ObjectOutputStream out = new ObjectOutputStream( new BufferedOutputStream( output ) );
		out.writeObject( obj );
		IOUtils.closeQuietly( out );
	}

	/** Write Object xml to bytes */
	public static byte[] serializeAsXML( Serializable obj ) {
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		serializeAsXML( obj, out );
		return out.toByteArray();
	}

	/** Write xml Object to file */
	public static void serializeAsXML( Serializable obj, File content ) throws IOException {
		serializeAsXML( obj, new FileOutputStream( content ) );
	}

	/** Write xml Object to outputstream */
	public static void serializeAsXML( Serializable obj, OutputStream output ) {
		XMLEncoder out = new XMLEncoder( new BufferedOutputStream( output ) );
		out.writeObject( obj );
		out.flush();
		out.close();
	}

	/** Serialize as XStream */
	public static String serializeAsXStream( Serializable obj ) {
		return serializeAsXStream( obj, new ReferenceByXPathMarshallingStrategy( ReferenceByXPathMarshallingStrategy.RELATIVE ) );
	}

	/** Serialize as XStream */
	public static String serializeAsXStream( Serializable obj, MarshallingStrategy strat ) {
		XStream s = new XStream( new PureJavaReflectionProvider() );
		s.setMarshallingStrategy( strat );
		return s.toXML( obj );
	}

	/** Serialize as XStream */
	public static void serializeAsXStream( Serializable obj, File out ) throws IOException {
		serializeAsXStream( obj, new ReferenceByXPathMarshallingStrategy( ReferenceByXPathMarshallingStrategy.RELATIVE ), out );
	}

	/** Serialize as XStream */
	public static void serializeAsXStream( Serializable obj, MarshallingStrategy strat, File out ) throws IOException {
		serializeAsXStream( obj, strat, new BufferedOutputStream( new FileOutputStream( out ) ) );
	}

	/**
	 * Serialize as XStream
	 * ß
	 */
	public static void serializeAsXStream( Serializable obj, MarshallingStrategy strat, OutputStream out ) {
		XStream s = new XStream( new PureJavaReflectionProvider() );
		s.setMarshallingStrategy( strat );
		s.toXML( obj, out );
	}

	/** Serialize as XStream */
	public static void serializeAsXStream( Serializable obj, OutputStream out ) {
		serializeAsXStream( obj, new ReferenceByXPathMarshallingStrategy( ReferenceByXPathMarshallingStrategy.RELATIVE ), out );
	}
}